<?php

/**
 * @mod_postfix.php
 * webPanel module for postfix management
 *
 */

/**
 * Main processing function
 *
 * Validates request and call internal function to process it
 *
 * returns:
 * 0	function result
 * -1	invalid authorization
 * -2	invalid method
 */
function processRequest($method_name, $params, $app_data)
{
	error_log("» mod_postfix: processRequest ".$method_name);
	global $conf;
	
	// validate autorization key
	if (strcmp($params[0], $conf['auth_key']) != 0)
	{
		error_log(" mod_postfix: invalid authorization key.");
		return -1;
	}
	
	switch ($method_name)
	{
		case "mail.listDomains":
			return listDomainsFunc($params[1], $params[2]);
		case "mail.listDomainUsers":
			return listDomainUsersFunc($params[1], $params[2], $params[3]);
		case "mail.newDomain":
			return newDomainFunc($params[1]);
		case "mail.newUser":
			return newUserFunc($params[1],$params[2]);
		case "mail.delDomain":
			return delDomainFunc($params[1]);
		case "mail.setPass":
			return setPassFunc($params[1],$params[2]);
		case "mail.delUser":
			return delUserFunc($params[1]);
	}
	error_log(" mod_postfix: invalid method.");
	return -2;
}

/**
 * Gather a list of configured domains in the mail server
 *
 * @lowLimit
 *   Index from list to first domain to return
 * @nRecords
 *   Number of records to return
 *
 * @return
 *   An array with a limited list of domains
 */
function listDomainsFunc($lowLimit=0, $nRecords=-1)
{
	error_log("» mod_postfix: listDomainsFunc");
	global $conf;
	
	$domain_list = array();
	
	// read main.cf configuration file into array
	$main_cf_array = file($conf['postfix']['main']);
	
	// search index with "virtual_mailbox_domains" configuration
	$index = 0;
	for ($i=0; $i<count($main_cf_array); $i++)
		if (strpos($main_cf_array[$i], "irtual_mailbox_domains =") > 0)
			break;
	
	// clean resulting string
	$domain_list_str = str_replace("virtual_mailbox_domains =", "", $main_cf_array[$i]);
	$domain_list_tmp = split('[[:space:]]', $domain_list_str);
	for ($i=0; $i<count($domain_list_tmp); $i++)
		if (strlen($domain_list_tmp[$i]) > 1)
			$domain_list[count($domain_list)] = $domain_list_tmp[$i];
	sort($domain_list);
	return limit($domain_list,$lowLimit,$nRecords);
}

/**
 * Gather a list of configured accounts within the specified domain
 *
 * @domain
 *   Domain to list users from
 * @lowLimit
 *   Index from list to first user to return
 * @nRecords
 *   Number of records to return
 *
 * @return
 *   An array with a limited list of accounts
 */
function listDomainUsersFunc($domain, $lowLimit=0, $nRecords=-1)
{
	error_log("» mod_postfix: listDomainUsersFunc");
	global $conf;
	
	// read user account file
	$user_accounts = file($conf['postfix']['vmailbox']);
	
	// select given domain accounts
	$domain_user_accounts = array();
	for ($i = 0; $i < count($user_accounts); $i++)
		if (strpos($user_accounts[$i], $domain) > 0)
		{
			$user = split('[[:space:]]', $user_accounts[$i]);
			$domain_user_accounts[count($domain_user_accounts)] = $user[0];
		}
	
	// sort, limit e return accounts
	sort($domain_user_accounts);
	return limit($domain_user_accounts,$lowLimit,$nRecords);
}

/**
 * Insert (and configure) a new mail domain
 *
 * @domainName
 *   New domain name
 *
 * @return
 * 0	success
 * -1	domain already configured
 * -2	error opening main.cf file
 */
function newDomainFunc($domainName)
{
	error_log("» mod_postfix: newDomainFunc");
	global $conf;
	
	$new_domain = $domainName;
	$str_main_cf = $conf['postfix']['main'];
	$str_main_cf_bak = `cp -p "$str_main_cf" "$str_main_cf".bak`;
	$main_cf=file($str_main_cf);
	$new_main_cf = array();
	for ($i=0; $i<count($main_cf); $i++)
	{
		if (strpos($main_cf[$i], "irtual_mailbox_domains =") > 0)
		{
			if (strpos($main_cf[$i], " ".$new_domain) == 0)
			{
				$main_cf[$i] = str_replace("\n", "", $main_cf[$i]);
				$main_cf[$i] = $main_cf[$i]." ".$new_domain."\n";
			}
			else
			{
				error_log("» mod_postfix: domain already configured.");
				return -1;
			}
		}
		$new_main_cf[$i] = $main_cf[$i];
	}
	$f = fopen($str_main_cf, "w");
	if ($f == FALSE)
	{
		error_log("» mod_postfix: error opening $str_main_cf.");	
		return -2;
	}
	for ($i=0; $i<count($main_cf); $i++)
		fwrite($f, $new_main_cf[$i]); 
	fclose($f);
	exec("sudo postfix reload"); 
	return 0;
}

/**
 * Remove a mail domain
 *
 * @domainName
 *   Domain name to remove
 *
 * @return
 * 0	success
 * -1	domain has configured accounts
 * -2	error removing domain
 * -3	error opening main.cf
 */
function delDomainFunc($domainName)
{
	error_log("» mod_postfix: delDomainFunc");
	global $conf;
	
	// Can only remove domain with no associated accounts!
	if ( count(listDomainUsersFunc($domainName,0,1)) > 0 )
	{
		error_log(" mod_postfix: Domain has accounts configured");
		return -1;
	}
	
	$str_main_cf = $conf['postfix']['main'];
	$str_main_cf_bak = `cp -p "$str_main_cf" "$str_main_cf".bak`;
	$main_cf=file($str_main_cf);
	$new_main_cf = array();
	for ($i=0; $i<count($main_cf); $i++)
	{
		if (strpos($main_cf[$i], "irtual_mailbox_domains =") > 0)
		{
			if (strpos($main_cf[$i], " ".$domainName) > 0)
			{
				$main_cf[$i] = str_replace("\n", "", $main_cf[$i]);
				$main_cf[$i] = str_replace(" ".$domainName, "", $main_cf[$i])."\n";
			}
			else
			{
				error_log(" mod_postfix: error removing domain.");
				return -2;
			}
		}
		$new_main_cf[$i] = $main_cf[$i];
	}
	$f = fopen($str_main_cf, "w");
	if ($f == FALSE)
	{
		error_log("» mod_postfix: error opening $str_main_cf.");	
		return -3;
	}
	for ($i=0; $i<count($main_cf); $i++)
		fwrite($f, $new_main_cf[$i]); 
	fclose($f);
	exec("sudo postfix reload"); 
	return 0;
}

/**
 * Insert (and configure) a new mail account
 *
 * @domainName
 *   Domain of new account
 * @userName
 *   New account name
 *
 * @return
 * 0	success
 * -1	invalid user name
 * -2	user already configured
 */
function newUserFunc($domainName, $userName)
{
	error_log("» mod_postfix: newUserFunc");
	global $conf;

	if (strpos($userName, '@') != FALSE)
	{
		error_log("» mod_postfix: newUserFunc: invalid user name.");
		return -1;
	}
	if (strpos($userName, ' ') != FALSE)
	{
		error_log("» mod_postfix: newUserFunc: invalid user name.");
		return -1;
	}
	
	$domain = $domainName;
	$user = $userName;
	$vmailbox = $conf['postfix']['vmailbox'];
	$vuid = $conf['postfix']['vuid'];
	$vgid = $conf['postfix']['vgid'];
	
	$line_to_add = "$user@$domain\t$domain/$user/Maildir/";
	$user_exists = `cat "$vmailbox" | grep "$line_to_add"`;
	if (strlen($user_exists) > 0)
	{
		error_log("» mod_postfix: user already exists.");
		return -2;
	}

	exec("echo \"$line_to_add\" >> $vmailbox");

	exec("echo \"$user@$domain\t5000\" >> $vuid");
	exec("echo \"$user@$domain\t5000\" >> $vgid");

	exec("postmap $vmailbox $vuid $vgid");
	
	exec("sudo userdb \"$user@$domain\" set home=".$conf['postfix']['maildir']."/$domain/$user/ mail=".$conf['postfix']['maildir']."/$domain/$user/Maildir uid=5000 gid=5000");
	
	exec("echo \"$user@$domain\" | sudo userdbpw | sudo userdb \"$user@$domain\" set systempw");

	exec("sudo makeuserdb");
	return 0;
}

/**
 * Set user password
 *
 * @userName
 *   New account name
 *
 * @newPassword
 *   New account's password
 *
 * @return
 *   0 on success
 */
function setPassFunc($userName, $newPass)
{
	error_log("» mod_postfix: setPassFunc");
	global $conf;

	exec("echo \"$newPass\" | sudo userdbpw | sudo userdb \"$userName\" set systempw");

	exec("sudo makeuserdb");
	return 0;
}

/**
 * Remove unwanted mail account
 *
 * @domainName
 *   Domain of account
 * @userName
 *   Account to remove
 *
 * @return
 * 0	success
 * -1	error opening vmailbox
 * -2	error opening vuid
 * -3	error opening vgid
 */
function delUserFunc($userName)
{
	error_log("» mod_postfix: delUserFunc");
	global $conf;
	
	$userData = split('@', $userName);
	$domain = $userData[1];
	$user = $userData[0];
	
	$vmailbox = $conf['postfix']['vmailbox'];
	$vuid = $conf['postfix']['vuid'];
	$vgid = $conf['postfix']['vgid'];

	// Remove account from vmailbox file
	$line_to_remove = "$domain/$user/Maildir/";
	$str_vmailbox=file($vmailbox);
	$new_vmailbox=array();
	for ($i=0; $i<count($str_vmailbox); $i++)
	{
		if (strpos($str_vmailbox[$i], $line_to_remove) == FALSE)
		{
			$new_vmailbox[count($new_vmailbox)] = $str_vmailbox[$i];
		}
	}
	$f = fopen($vmailbox, "w");
	if ($f == FALSE)
	{
		error_log("» mod_postfix: error opening $vmailbox");
		return -1;
	}
	for ($i=0; $i<count($new_vmailbox); $i++)
		fwrite($f, $new_vmailbox[$i]); 
	fclose($f);

	// remove account from vuid
	$line_to_remove = "$userName";
	$str_vuid=file($vuid);
	$new_vuid=array();
	for ($i=0; $i<count($str_vuid); $i++)
	{
		$tst_str = split("\t", $str_vuid[$i]);
		if (strcmp($userName, $tst_str[0]) != 0)
			$new_vuid[count($new_vuid)] = $str_vuid[$i];
	}
	return -1;
	$f = fopen($vuid, "w");
	if ($f == FALSE)
	{
		error_log("» mod_postfix: error opening $vuid");
		return -2;
	}
	for ($i=0; $i<count($new_vuid); $i++)
		fwrite($f, $new_vuid[$i]); 
	fclose($f);

	// remove account from vgid
	$line_to_remove = "$userName";
	$str_vgid=file($vgid);
	$new_vgid=array();
	for ($i=0; $i<count($str_vgid); $i++)
	{
		$tst_str = split("\t", $str_vgid[$i]);
		if (strcmp($userName, $tst_str[0]) != 0)
			$new_vgid[count($new_vgid)] = $str_vgid[$i];
	}
	return -1;
	$f = fopen($vgid, "w");
	if ($f == FALSE)
	{
		error_log("» mod_postfix: error opening $vgid");
		return -3;
	}
	for ($i=0; $i<count($new_vgid); $i++)
		fwrite($f, $new_vgid[$i]); 
	fclose($f);

	exec("postmap $vmailbox $vuid $vgid");
	
	exec("sudo userdb \"$user@$domain\" del");
	
	exec("sudo makeuserdb");
	return 0;
}

?>
